package com.mimo.comet.grpc;

import java.util.Optional;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.mimo.comet.config.LocalCometServerConfig;
import com.mimo.comet.dao.ISessionDao;
import com.mimo.comet.provider.ISession;
import com.mimo.common.logic.code.StatusCode;
import com.mimo.common.logic.dto.msg.BaseDispatchMessage;
import com.mimo.common.rpc.proto.BaseResponseProto.BaseResponse;
import com.mimo.common.rpc.proto.CometMessageProxyGrpc;
import com.mimo.common.rpc.proto.DispatchMessageProto.DispatchMessage;
import com.mimo.common.utils.JsonUtils;

import io.grpc.stub.StreamObserver;
import net.devh.boot.grpc.server.service.GrpcService;

@GrpcService
public class CometMessageGrpc extends CometMessageProxyGrpc.CometMessageProxyImplBase {

  private static final Logger log = LoggerFactory.getLogger(CometMessageGrpc.class);

  @Autowired
  private ISessionDao sessionDao;

  @Autowired
  private LocalCometServerConfig config;

  /**
   * 对于发送失败有以下可能：
   * <li>用户不在本机连接上，可能转移到其他物理设备上了
   * <li>用户已经断连了
   * <li>本地代码异常有错误
   * <p>
   * 基于以上情况，都会返回false. 对于业务消费者需要对这种false情况进行重试处理，由调用方决定。
   */
  @Override
  public void send(DispatchMessage request, StreamObserver<BaseResponse> responseObserver) {
    StatusCode statusCode = StatusCode.Success;

    BaseDispatchMessage msg = BaseDispatchMessage.convert(request);
    Optional<ISession> opt = sessionDao.findByUid(msg.getTarget());

    if (opt.isPresent()) {
      try {
        opt.get().write(JsonUtils.toJsonString(msg));
      } catch (Exception ex) {
        statusCode = StatusCode.UserUnavailable;
        log.warn("向user[{}]发送消息失败", msg.getTarget(), ex);
      }
    } else {
      statusCode = StatusCode.CometUserUnlocated;
      log.warn("本机:{},无法找到对应的user[{}]以完成消息推送", JsonUtils.toJsonString(config.getZone()), msg.getTarget());
    }
    responseObserver.onNext(statusCode.toResp());
    responseObserver.onCompleted();
  }

}
